#ifndef __CACHEFLEX_DEVEL_FRAME_TYPES__
#define __CACHEFLEX_DEVEL_FRAME_TYPES__
#include <unistd.h>
#include <asm-generic/errno.h>
#include "include/base-api/cf_base_types.h"

/* cf_store_handle_t是每个内存块的元数据，它由store模块产生，
 * 根据它可以得到它对应的内存指针，并且可以增加和减去这块内存的引用计数
 */
typedef uint64_t cf_store_handle_t;

/* cf_reclaim_handle_t是reclaim模块的元数据，
 * 在reclaim模块中，用它来标记每个内存块，它由reclaim模块产生，
 * 当一个内存块被访问的时候要通知reclaim模块，某个cf_reclaim_handle_t对应的内存块被访问了
 */
typedef uint64_t cf_reclaim_handle_t;

/* 框架为每个key-value维护一个item_handle_t, item_handle_t是kv对的元
 * 数据，也是index模块操作的对象数据
 * item_handle_t可以理解为是每对key-value的元数据，所以它是index模块中的value，
 * 根据key可以找到它对应的item_handle_t，从item_handle_t中可以获取value的地址
 * 由于cache可以存储小的变长数据，因此可能多个key-value对存放在一个内存块中，
 * 即多个item_handle_t中的store_handle是相同的
 */
struct cf_item_handle;
typedef struct cf_item_handle cf_item_handle_t;

typedef void (*cf_index_scan_callback_pt) (void *key, cf_item_handle_t *ih, void *args);

////////////////////////////////////////////////////////////////////////////////////////////////////

/*
 * 以下均为框架开发者需要实现的接口
 */

/*
 * 索引模块接口
 * index模块存储key到item_handle_t的映射
 * item_handle_t的内存由框架管理
 */
struct cf_index_interface
{
    void *(*construct)(const int64_t item_num, struct cf_index_interface *interface);
    void (*destruct)(void *instance);

    int (*put)(cacheflex_t *cache, void *key, cf_item_handle_t *ih);
    int (*get)(cacheflex_t *cache, void *key, cf_item_handle_t **ih);
    int (*erase)(cacheflex_t *cache, void *key);
    int (*scan)(cacheflex_t *cache, cf_index_scan_callback_pt scan_callback, void *args);
};

/*
 * 替换算法接口
 * reclaim为每个内存块分配唯一的handle
 * 访问某个item时通过handle来通知access事件
 */
struct cf_reclaim_interface 
{
    void *(*construct)(const int64_t reclaim_num);
    void (*destruct)(void *instance);

    int (*assign)(cacheflex_t *cache, const cf_store_handle_t sh, cf_reclaim_handle_t *rh);
    int (*access)(cacheflex_t *cache, const cf_reclaim_handle_t rh);
    int (*reclaim)(cacheflex_t *cache);
};

// 存储引擎接口
// 存储cache中key-value的实体数据
// 要支持多级存储 实现操作多级存储的接口
// 其中ref_buffer为根据handle获取空间指针
// deref_buffer与ref_buffer配对使用 dirty表示指向的空间是否被修改过
// (注意：需要处理在deref_buffer之前free的情况)
struct cf_store_interface
{
    void *(*construct)(const int64_t store_size);
    void (*destruct)(void *instance);

    int (*alloc)(cacheflex_t *cache, const int64_t nbyte, cf_store_handle_t *sh);
    void (*free)(cacheflex_t *cache, const cf_store_handle_t sh);
    void *(*get_buffer)(cacheflex_t *cache, const cf_store_handle_t sh);

    int (*get_level_num)(cacheflex_t *cache, int64_t *level_num);
    int (*get_level_percent)(cacheflex_t *cache, const int64_t level, int64_t *percent);
    int (*get_store_level)(cacheflex_t *cache, const cf_store_handle_t sh, int64_t *level);
    int (*promote_level)(cacheflex_t *cache, const cf_store_handle_t sh);
    int (*demote_level)(cacheflex_t *cache, const cf_store_handle_t sh);
};

#ifndef __CACHEFLEX_BASE_TYPES__
    typedef struct cf_index_interface cf_index_interface_t;
    typedef struct cf_store_interface cf_store_interface_t;
    typedef struct cf_reclaim_interface cf_reclaim_interface_t;
#endif
#endif // __CACHEFLEX_DEVEL_FRAME_TYPES__

